package functions;

import java.io.BufferedWriter;
import java.io.FileNotFoundException;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.util.Random;

import javax.swing.JOptionPane;

import types.Block;
// create data set of tests based on the code blocks of the generated program
public class CreateTestsDS {          
	static int countProc = 0;
	static int countTest = 0;
	private int tests = 0;
	public CreateTestsDS(Block[] blocks, int progSize, Boolean excep) {
		int totalTests = 550;
		String blockType = "";
		String[] testSet = new String[totalTests];
		int lineNumber = 1;
		int sum, k = 0, rnd, r, temp, sum2;
		int elseLine = 0;
		int rndEx, exLine;
		Random randomGenerator = new Random();

		for (int j = 0; j < totalTests; j++) {  // for loop for traces
			lineNumber = 1;
			testSet[j] = "";

			for (int i = 0, exFlag = 0; i < blocks.length && exFlag == 0; i++) {

				blockType = blocks[i].getType(); 
				if (blockType == "regular") {     //regular type code block
					sum = blocks[i].getLine();
					if(i==0){
						testSet[j] += "" + lineNumber;
						for (k = lineNumber+1; k < sum + lineNumber; k++)
							testSet[j] += "," + k;
					}
					else{
						for (k = lineNumber; k < sum + lineNumber; k++)
							testSet[j] += "," + k;
					}
					lineNumber = k;

				}

				if (blockType == "if") {         // if type code block
					if(blocks[i].getChecked()){
						rnd = randomGenerator.nextInt(4) + 1;
						sum = blocks[i].getLine();
						rndEx = randomGenerator.nextInt(100) + 1;
	
						if (rndEx < 10 && excep) { // 10% chance to enter exception
							exLine = randomGenerator.nextInt(sum + lineNumber)
									+ lineNumber;
							for (k = lineNumber; k < exLine; k++)
								testSet[j] += "," + k;
							exFlag = 1;
						} else {
							if (rnd == 1) { // 25% chance no to enter if
								testSet[j] += "," + lineNumber;
	
							} else {
								for (k = lineNumber; k < sum + lineNumber; k++)
									testSet[j] += "," + k;
							}
							lineNumber = lineNumber + sum + 1;
						}
					}
					else{
						sum = blocks[i].getLine();
						for (k = lineNumber; k < sum + lineNumber; k++)
							testSet[j] += "," + k;
						lineNumber = lineNumber + sum + 1;
					}
						
				}

				if (blockType == "if_else") {     // if-else type code block
					if(blocks[i].getChecked()){
						rnd = randomGenerator.nextInt(1) + 1; // 1- if 2-else
						sum = blocks[i].getLine();
						rndEx = randomGenerator.nextInt(100) + 1;
	
						if (rnd == 1) { // if
							elseLine = 0;
							sum2 = (int) sum / 2;
						} else { // else
							elseLine = (int) sum / 2;
							sum2 = sum;
						}
	
						if (rndEx >= 10) {
							for (k = lineNumber + elseLine; k < sum2 + lineNumber; k++)
								testSet[j] += "," + k;
							lineNumber = lineNumber + sum + 1;
						} else if (excep){
							exLine = randomGenerator.nextInt(sum2 + lineNumber)
									+ lineNumber + elseLine;
							for (k = lineNumber + elseLine; k < exLine; k++)
								testSet[j] += "," + k;
							exFlag = 1;
						}
					}
					else{
						sum = blocks[i].getLine();
						for (k = lineNumber; k < sum + lineNumber; k++)
							testSet[j] += "," + k;
						lineNumber = lineNumber + sum + 1;
					}

				}

				if (blockType == "for") {                  // for type code block
					if(blocks[i].getChecked()){
						rnd = randomGenerator.nextInt(10) + 5; // 5..10 times for a
																// for
						rndEx = randomGenerator.nextInt(100) + 1;
						sum = blocks[i].getLine();
						temp = lineNumber;
	
						if (rndEx < 10 && excep) { // 10% chance to enter exception
							exLine = randomGenerator.nextInt(sum + lineNumber)
									+ lineNumber;
							for (k = lineNumber; k < exLine; k++)
								testSet[j] += "," + k;
							exFlag = 1;
						} else {
							for (r = 0; r < rnd; r++) {
								for (k = temp; k < sum + temp; k++) {
									testSet[j] += "," + k;
								}
								temp = lineNumber;
							}
							lineNumber = lineNumber + sum + 1;
						}
					}
					else{
						sum = blocks[i].getLine();
						for (k = lineNumber; k < sum + lineNumber; k++)
							testSet[j] += "," + k;
						lineNumber = lineNumber + sum + 1;
					}
						
				}

				if (blockType == "while") {         //while type code block
					if(blocks[i].getChecked()){
						rnd = randomGenerator.nextInt(10) + 3; // 3..13 times for a
																// while
						rndEx = randomGenerator.nextInt(100) + 1;
						sum = blocks[i].getLine();
						temp = lineNumber;
	
						if (rndEx < 10 && excep) { // 10% chance to enter exception
							exLine = randomGenerator.nextInt(sum + lineNumber)
									+ lineNumber;
							for (k = lineNumber; k < exLine; k++)
								testSet[j] += "," + k;
							exFlag = 1;
						} else {
							for (r = 0; r < rnd; r++) {
								for (k = temp; k < sum + temp; k++) {
									testSet[j] += "," + k;
								}
								temp = lineNumber;
							}
							lineNumber = lineNumber + sum + 1;
						}
					}
					else{
						sum = blocks[i].getLine();
						for (k = lineNumber; k < sum + lineNumber; k++)
							testSet[j] += "," + k;
						lineNumber = lineNumber + sum + 1;
					}
				}

				if (blockType == "func") {           // func type code block
					if(blocks[i].getChecked()){
						sum = blocks[i].getLine();
						rndEx = randomGenerator.nextInt(100) + 1;
	
						if (rndEx < 16 && excep) { // 15% chance to enter exception
							exLine = randomGenerator.nextInt(sum + lineNumber)
									+ lineNumber;
							for (k = lineNumber; k < exLine; k++)
								testSet[j] += "," + k;
							exFlag = 1;
						} else {
							for (k = lineNumber; k < sum + lineNumber; k++)
								testSet[j] += "," + k;
							lineNumber = lineNumber + sum + 1;
						}
					}
						else{
							sum = blocks[i].getLine();
							for (k = lineNumber; k < sum + lineNumber; k++)
								testSet[j] += "," + k;
							lineNumber = lineNumber + sum + 1;
						}
				}

			}// end for
		}

		makeTextFile(testSet, totalTests);
		if(countProc == 1){
			countTest = tests;
			JOptionPane.showMessageDialog(null,"The file 'test_data_set.txt' created ! added "+countTest+" tests.");
		}
		else{
			JOptionPane.showMessageDialog(null,"The file 'test_data_set.txt' was updated with new tests: "+(countTest+1)+" to "+(countTest+1+tests));
			countTest += tests;
		}
	}
		

	public void makeTextFile(String[] blocksLines, int progSize)
	{
		// add traces as tests into our data set file with duplications
		countProc++;
		if(countProc == 1){
			PrintWriter writer = null;
			try {
				writer = new PrintWriter("test_data_set.txt", "UTF-8");
			} catch (FileNotFoundException e) {
				e.printStackTrace();
			} catch (UnsupportedEncodingException e) {
				e.printStackTrace();
			}
			
			for(int i=0	;	i<progSize	;	i++){
				double multTestD = 0.0;
				int multTest = 0;
				RandomGaussian RG = new RandomGaussian(1.0,0.7,1);
				multTestD = RG.getRes();
				multTestD = multTestD + 0.4;
				multTest = (int)multTestD;
				if(multTest<0)
					multTest=0;
				String test = blocksLines[i];
				
				for(int j=0; j<multTest; j++){
					writer.println(test);
					writer.println();
					tests++;
				}				
			}
		
			writer.close();
		}  // end if counter 1
		
		else{
			
			BufferedWriter out = null;
			try  
			{
			    FileWriter fstream = new FileWriter("test_data_set.txt", true); 
			    out = new BufferedWriter(fstream);
			    
			    
				for(int i=0	;	i<progSize	;	i++){
					double multTestD = 0.0;
					int multTest = 0;
					RandomGaussian RG = new RandomGaussian(1.0,0.7,1);
					multTestD = RG.getRes();
					multTestD = multTestD + 0.4;
					multTest = (int)multTestD;
					if(multTest<0)
						multTest=0;
					for(int j=0; j<multTest; j++){
						out.write(blocksLines[i]);
						out.write("\n\n");
						tests++;
					}
				}
	
			    
			}
			catch (IOException e)
			{
			    System.err.println("Error: " + e.getMessage());
			}
			finally
			{
			    if(out != null) {
			        try {
						out.close();
					} catch (IOException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
			    }
			}
		}		
	}
}
